using System;
using System.Collections;
using System.Collections.Generic;
using System.Collections.Specialized;
using Neo.Core;
using Neo.Core.Qualifiers;

namespace Neo.Framework
{
	/// <summary>
	/// A good base class for your query templates. CodeGen/Norque uses these.
	/// </summary>
	
	public class QueryTemplate : IFetchSpecification
	{
		//--------------------------------------------------------------------------------------
		//	Fields and constructors
		//--------------------------------------------------------------------------------------

		private IEntityMap entityMap;
		private ListDictionary queryValues;
		private int fetchLimit;
		private PropertyComparer[] sortOrderings;
		private string[] spans;
        private RefreshStrategy refreshStrategy;
	    private Dictionary<String, object[]> pathValues;

	    protected QueryTemplate(IEntityMap anEntityMap)
		{
			entityMap = anEntityMap;
			queryValues = new ListDictionary();
            pathValues = new Dictionary<string, object[]>();
			fetchLimit = -1;
		}

		
		//--------------------------------------------------------------------------------------
		//	Protected properties
		//--------------------------------------------------------------------------------------

        protected virtual IDictionary QueryValues
		{
			get { return queryValues; }
		}

        protected virtual IDictionary PathValues
        {
            get { return pathValues; }
        }
	
		//--------------------------------------------------------------------------------------
		//	Public properties
		//--------------------------------------------------------------------------------------

		public virtual IEntityMap EntityMap
		{
			get { return entityMap; }
		}

        public virtual Qualifier Qualifier
        {
            get
            {
                int cnt;

                if((cnt = queryValues.Count + pathValues.Count) == 0)
                {
                    return null;
                }
                ArrayList list = new ArrayList(cnt);

                foreach (DictionaryEntry e in queryValues)
                {
                    list.Add(ForKeyValuePair((string)e.Key, e.Value));
                }
                foreach (KeyValuePair<string, object[]> pair in pathValues)
                {
                    list.Add(Qualifier.Format(pair.Key, pair.Value));
                }
                if (list.Count == 1)
                {
                    return list[0] as Qualifier;
                }
                return new AndQualifier(list);
            }
        }

		public virtual Int32 FetchLimit
		{
			get { return fetchLimit; }
			set { fetchLimit = value; }
		}

		public virtual PropertyComparer[] SortOrderings
		{
			get { return sortOrderings; }
			set { sortOrderings = value; }
		}

		public virtual string[] Spans
		{
			get { return spans; }
			set { spans = value; }
		}

        public RefreshStrategy RefreshStrategy
        {
            get { return refreshStrategy; }
            set { refreshStrategy = value; }
        }

        public void AddPathQualifier(string path, params object[] args )
        {
            pathValues.Add(path, args);
        }

        protected virtual PropertyQualifier ForKeyValuePair(string aKey, object aValue)
        {
            String valueAsString = aValue as string;
            if ((valueAsString != null) && (valueAsString.IndexOf("%") >= 0))
                return new PropertyQualifier(aKey, new LikePredicate(valueAsString));
            return new PropertyQualifier(aKey, new EqualsPredicate(aValue));

        }
	}
}
